TITLE MASM Template						(main.asm)

; Description:  Thomas Lachin CSC208 Final Project
;				PDP8-Simulation

INCLUDE Irvine32.inc
INCLUDE PDP8.inc

;--------------------------------------------------------------------------
;--------------------------------------------------------------------------DATA
;--------------------------------------------------------------------------
.data

;This variable becomes the next WORD in PDP8Memory in order to do calculations			
PDP8Code WORD 				0000000000000000b		

;----Actual PDP8 variables
;---------------------------Insert Instructions into Memory here--------------------------------------
PDP8Memory WORD				0000001000000101b, 0000001000000110b, 0000011000000111b, 0000000000000000b,
							0000000000000000b, 0000000000000001b, 0000000000000111b, 0000000000000000b
							
programCounter WORD			0
accumulator WORD			0
link BYTE					0

memory WORD	4096 DUP		(0)
currentAddress WORD			0
addressForInstruction WORD	0
effectiveAddress WORD		0o

;----Flags for what is currently happening for the instruction
isIndirect WORD				0
isPage WORD					0 

;----Storage for what the address was in octal
offsetAddressStorageOctal WORD	0o
fiveBitAddressStorageOctal WORD	0o
pageAddressStorageOctal WORD 	0o
wholeAddressStorageOctal WORD	0o
addressStorage WORD				0o


;----Variables used to mask bits to convert from binary to octal
indirectBitFind WORD		0000000100000000b		;Indirect bit comparison to get only single bit out of the WORD
pageBitFind WORD 			0000000010000000b		;Page bit comparsion get a single bit out of the WORD
octalMask WORD				0000000000000111b
;---First five bit masking
fiveBitFind WORD			0000111110000000b
fiveBitFind_Last WORD		0000110000000000b		;left over of 2 bits, so only check those
;---Offset address bit masking
offsetBitFind WORD			0000000001111111b
offsetBitFind_Last WORD		0000000001000000b		;left over of 1 bit, so only check that 
;---Whole instruction bit masking
wholeBitFind WORD			0000111111111111b

;----Storage for specific bits
opCodeStorage WORD			0						;Remembers which of the 8 opCode calls were made for this memory

;----Formatted output strings
;---OpCode
opCodePrompt BYTE "OpCode: ", 0
opCodeAND BYTE "AND", 0
opCodeTAD BYTE "TAD", 0
opCodeISZ BYTE "ISZ", 0
opCodeDCA BYTE "DCA", 0
opCodeJMS BYTE "JMS", 0
opCodeJMP BYTE "JMP", 0
opCodeIOT BYTE "IOT", 0
opCodeOPR BYTE "OPR", 0
;---Indirect Bit
indirectBitPrompt BYTE "Indirect Bit: ", 0
;---Page Bit
pageBitPrompt BYTE "Page Bit: ", 0
;---Address
addressPrompt BYTE "Address in Octal: ",0 



;--------------------------------------------------------------------------
;--------------------------------------------------------------------------CODE
;--------------------------------------------------------------------------
.code

main PROC
	MOV eax, 0
	MOV edx, 0
	MOV ebx, 0
	MOV ecx, LENGTHOF PDP8Memory
	MOV ebx, OFFSET PDP8Memory
	
	.WHILE ecx > 0
		
		MOV dx, [ebx+eax]
		;MOV currentAddress, dx
		MOV PDP8Code, dx
		
		CALL ReadyInstruction
		CALL CallOperation
		
		;MOV ax, programCounter
		;ADD ebx, 2
		DEC ecx
		
		;MOV eax, 0
		;MOV ax, accumulator
		;CALL WriteDec
		
		MOV eax, 0
		MOV ax, programCounter
		
		
		CALL Crlf
	.ENDW
	
	;TESTING OUTPUT CODE FOR DEBUGGING
	;MOV eax, 0
	;MOV edx, 0
	;MOV ecx, 0
	
	;---- Since I am depositing into the last location, I am outputting that value
	;MOV cx, 14
	;MOV dx, WORD PTR PDP8Memory[ecx]
	;MOV ax, dx
	;CALL WriteDec
	;CALL Crlf
	
	;MOV ax, accumulator
	;CALL WriteDec
	;CALL Crlf
	
	exit
main ENDP

;--------------------------------------------------------------------------
;--------------------------------------------------------------------------Ready Instructions
;--------------------------------------------------------------------------


;-------------------------------------------
ReadyInstruction PROC USES eax edx ecx ebx
;
;Calls all the necessary functions to prepare program for calling instructions and operations
;-------------------------------------------
	CALL GetOpCode
	CALL GetIndirectBit
	CALL GetPageBit
	CALL GetCurrentPageAddress
	CALL GetOffsetAddress
	CALL GetWholeAddress
	CALL ReadyProperAddressForOperations
	ret
ReadyInstruction ENDP

;-------------------------------------------
GetOpCode PROC
;
;Gets the opCode from the first 3 bits
;-------------------------------------------
	MOV ax, PDP8Code
	SHR ax, 9				;Shift 9 to get to the first 3 bits
							;Which contain the opCode
							
	MOV edx, OFFSET opCodePrompt			;Just neat output for console
	CALL WriteString
	MOV edx, 0
	MOV opCodeStorage, 0
	
	;The following are if statements to output proper opCode instruction
	.IF ax ==  0
		MOV edx, OFFSET opCodeAND
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  1
		MOV edx, OFFSET opCodeTAD
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  2
		MOV edx, OFFSET opCodeISZ
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  3
		MOV edx, OFFSET opCodeDCA
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  4
		MOV edx, OFFSET opCodeJMS
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  5
		MOV edx, OFFSET opCodeJMP
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  6
		MOV edx, OFFSET opCodeIOT
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	.IF ax ==  7
		MOV edx, OFFSET opCodeOPR
		MOV opCodeStorage, ax
		CALL WriteString
		CALL Crlf
	.ENDIF
	
	MOV ax, PDP8Code					;reset instruction to its former status
	MOV edx, 0							;reset edx
	ret
GetOpCode ENDP

;-------------------------------------------
GetIndirectBit PROC 
;
;Gets the indirect bit from the 4th bit
;-------------------------------------------
	MOV eax, 0						;reset eax
	MOV ax, indirectBitFind			;set up tester WORD for instruction
	AND ax, PDP8Code				;AND it to see isolate the indirect bit
	
	MOV edx, OFFSET indirectBitPrompt			;Just neat output for console
	CALL WriteString
	MOV edx, 0
	.IF ax == 0
		MOV isIndirect, ax
		CALL WriteDec
	.ELSE
		MOV ax, 1
		MOV isIndirect, ax
		CALL WriteDec
	.ENDIF
	CALL Crlf
	
	MOV eax, 0
	MOV ax, PDP8Code
		
	ret
GetIndirectBit ENDP


;-------------------------------------------
GetPageBit PROC 
;
;Gets the page bit from the 5th bit
;-------------------------------------------
	MOV eax, 0						;reset eax
	MOV ax, pageBitFind				;set up tester WORD for instruction
	AND ax, PDP8Code				;AND it to see isolate the page bit
	
	MOV edx, OFFSET pageBitPrompt			;Just neat output for console
	CALL WriteString
	MOV edx, 0
	.IF ax == 0
		MOV isPage, ax
		CALL WriteDec
	.ELSE
		MOV ax, 1
		MOV isPage, ax
		CALL WriteDec
	.ENDIF
	CALL Crlf
	
	MOV eax, 0
	MOV ax, PDP8Code
		
	ret
GetPageBit ENDP

;-------------------------------------------
GetOffsetAddress PROC 
;
;Gets the address bits from the 6th bit to the 12th bit
;-------------------------------------------
	MOV eax, 0						;reset eax
	
	MOV edx, OFFSET addressPrompt			;Just neat output for console
	CALL WriteString
	MOV edx, 0
	CALL PrintAddressInOctal
	
	ret
GetOffsetAddress ENDP

;-------------------------------------------
PrintAddressInOctal PROC USES edx
;
;Gets the address bits from the 6th bit to the 12th bit
;-------------------------------------------
	MOV eax, 0						;reset registers
	MOV ecx, 0						;used to divide by 8 everytime
	MOV edx, 0
	
	;----First Octal Digit
	MOV ax, PDP8Code							;set up tester WORD for instruction
	AND ax, octalMask							;AND it to see to get the first 3 bits for octal conversion
	ADD cx, ax
	
	;----Second Octal Digit
	MOV eax, 0
	MOV ax, PDP8Code
	SHR ax, 3
	AND ax, octalMask
	
	;--Multiply by 10 to get second digit place
	MOV dx, ax
	SHL dx, 1
	SHL ax, 3
	ADD cx, dx
	ADD cx, ax
	
	;----Third Octal Digit
	MOV eax, 0
	MOV ax, PDP8Code
	SHR ax, 6
	AND ax, offsetBitFind_Last
	
	;--Multiply by 100 to get third digit place
	MOV dx, ax
	SHL ax, 7
	ADD cx, ax
	
	MOV ax, dx
	SHL ax, 6
	ADD cx, ax
	
	MOV ax, dx
	SHL ax, 2
	ADD cx, ax
	
	;----Output
	MOV eax, 0
	MOV ax, cx
	MOV offsetAddressStorageOctal, ax
	CALL WriteDec
	CALL Crlf
	
	ret
PrintAddressInOctal ENDP

;-------------------------------------------
GetCurrentPageAddress PROC 
;
;Gets the current page for this instruction
;-------------------------------------------
	MOV eax, 0						;reset registers
	MOV ecx, 0
	
	;----First Octal Digit
	MOV ax, PDP8Code
	AND ax, octalMask
	ADD cx, ax
	
	;----Second Octal Digit
	MOV eax, 0
	MOV ax, PDP8Code
	AND ax, fiveBitFind_Last
	ADD cx, ax
	
	MOV eax, 0
	MOV ax, cx
	MOV fiveBitAddressStorageOctal, ax
	
	ret
GetCurrentPageAddress ENDP

;-------------------------------------------
GetWholeAddress PROC 
;
;Gets the octal address for all 12 bits
;-------------------------------------------
	MOV eax, 0						;reset registers
	MOV ecx, 0
	MOV ax, fiveBitAddressStorageOctal
	ADD ax, offsetAddressStorageOctal
	MOV wholeAddressStorageOctal, ax
	ret
GetWholeAddress ENDP

;-------------------------------------------
ReadyProperAddressForOperations PROC 
;
;Based on the indirect and page bits, it stores the effective address in memory
;so the operations can use that address without figuring what the effective address is themselves
;-------------------------------------------
	MOV eax, 0						;reset registers
	MOV ecx, 0
	MOV edx, 0
	MOV edx, OFFSET PDP8Memory
	
	.IF isIndirect == 0		;----Direct effective address
		.IF isPage == 0
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			SHL ax, 1 
			MOV addressForInstruction, ax
		.ELSE
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			ADD ax, fiveBitAddressStorageOctal
			SHL ax, 1
			MOV addressForInstruction, ax
		.ENDIF
	.ELSE					;----Indirect effective address
		.IF isPage == 0
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			SHL ax, 1 
			MOV dx, PDP8Memory[ebx+eax]
			MOV PDP8Code, dx
			
			CALL GetCurrentPageAddress
			CALL GetOffsetAddress
			CALL GetWholeAddress
			
			MOV eax, 0
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			SHL ax, 1
			MOV addressForInstruction, ax
		.ELSE
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			ADD ax, fiveBitAddressStorageOctal
			SHL ax, 1
			MOV dx, PDP8Memory[ebx+eax]
			MOV PDP8Code, dx
			
			CALL GetCurrentPageAddress
			CALL GetOffsetAddress
			CALL GetWholeAddress
			
			MOV eax, 0
			MOV ax, offsetAddressStorageOctal
			MOV addressStorage, ax
			ADD ax, fiveBitAddressStorageOctal
			SHL ax, 1
			MOV addressForInstruction, ax
		.ENDIF
	.ENDIF
	
	ret
ReadyProperAddressForOperations ENDP



;--------------------------------------------------------------------------
;--------------------------------------------------------------------------PDP8 Operation Code Procedures
;--------------------------------------------------------------------------

;-------------------------------------------
CallOperation PROC USES eax edx ecx ebx
;
;Calls the proper operation code procedures based on the current memory's opCode
;-------------------------------------------
	.IF opCodeStorage == 0
		CALL opAND
	.ELSEIF opCodeStorage == 1
		CALL OpTAD
	.ELSEIF opCodeStorage == 2
		CALL OpISZ
	.ELSEIF opCodeStorage == 3
		CALL OpDCA
	.ELSEIF opCodeStorage == 4
		CALL OpJMS
	.ELSEIF opCodeStorage == 5
		CALL OpJMP
	.ELSEIF opCodeStorage == 6
		CALL OpIOT
	.ELSEIF opCodeStorage == 7
		CALL OpOPR
	.ENDIF
	ret
CallOperation ENDP

;-------------------------------------------
OpAND PROC ;USES eax ;edx ecx
;
;bit-wise logical AND
;C(AC) <- C(AC) AND C(EAddr)
;-------------------------------------------
	MOV eax, 0
	MOV edx, 0
	
	MOV ax, addressForInstruction
	MOV dx, PDP8Memory[eax]
	
	AND accumulator, dx
	Call IncrementProgramCounter
	ret
OpAND ENDP


;-------------------------------------------
OpTAD PROC ;USES eax edx ;ecx
;
;Twos Complement Add
;C(AC) <- C(AC) + C(EAddr)
;If carry out then complement Link Bit.
;-------------------------------------------
	MOV eax, 0
	MOV edx, 0
	
	MOV ax, addressForInstruction
	MOV dx, PDP8Memory[eax]
	MOV addressStorage, dx
	
	MOV ax, accumulator
	ADD ax, addressStorage
	
	MOV accumulator, ax
	Call IncrementProgramCounter
	ret
OpTAD ENDP

;-------------------------------------------
OpISZ PROC ;USES eax ;edx ecx
;
;Increment and Skip if Zero
;C(EAddr) <- C(EAddr) + 1
;If C(EAddr) = 0 then C(PC) <- C(PC) + 1
;-------------------------------------------
	MOV eax, 0
	MOV edx, 0
	
	MOV ax, addressForInstruction
	MOV dx, PDP8Memory[eax]
	MOV addressStorage, dx
	
	.IF addressStorage != 0
		INC addressStorage
	.ENDIF
	
	Call IncrementProgramCounter
	ret
OpISZ ENDP

;-------------------------------------------
OpDCA PROC ;USES eax ;edx ;ecx
;
;Deposit and Clear Accumulator
;C(EAddr) <- C(AC); C(AC) <- 0
;-------------------------------------------
	MOV eax, 0
	MOV edx, 0
	
	MOV ax, addressForInstruction
	MOV dx, PDP8Memory[eax]
	
	MOV dx, accumulator
	MOV PDP8Memory[eax], dx
	MOV accumulator, 0
	
	Call IncrementProgramCounter
	ret
OpDCA ENDP

;-------------------------------------------
OpJMS PROC ;USES eax ;edx ecx ebx
;
;JuMp to Subroutine
;C(EAddr) <- C(PC); C(PC) <- EAddr + 1
;-------------------------------------------
	MOV eax, 0
	MOV edx, 0
	MOV ebx, 0
	
	MOV ax, addressForInstruction
	MOV dx, PDP8Memory[ebx+eax]
	MOV PDP8Code, dx
	
	CALL ReadyInstruction
	CALL CallOperation
	
	CALL IncrementProgramCounter
	ret
OpJMS ENDP

;-------------------------------------------
OpJMP PROC ;USES eax ;edx ecx
;
;JuMP
;C(PC) <- EAddr
;-------------------------------------------
	MOV eax, 0
	MOV programCounter, 0
	MOV ax, addressForInstruction
	SHL ax, 1
	ADD programCounter, ax
	ret
OpJMP ENDP

;-------------------------------------------
OpIOT PROC ;USES eax ;edx ecx
;
;input/output transfer
;-------------------------------------------
	
	ret
OpIOT ENDP

;-------------------------------------------
OpOPR PROC ;USES eax ;edx ecx
;
;microcoded operations
;-------------------------------------------
	
	ret
OpOPR ENDP

;-------------------------------------------
IncrementProgramCounter PROC ;USES eax ;edx ecx
;
;Increments PC
;-------------------------------------------
	ADD programCounter, 2
	ret
IncrementProgramCounter ENDP




;--------------------------------------------------------------------------END OF FILE
END main				